<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>基础字体子集化工具</title>
    <script src="https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js"></script>
    <style>
      :root {
        --primary-color: #6c5ce7;
        --primary-light: #a29bfe;
        --text-color: #2d3436;
        --bg-color: #fff;
        --border-color: #dfe6e9;
        --success-color: #00b894;
        --error-color: #d63031;
      }

      body {
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
        max-width: 800px;
        margin: 0 auto;
        padding: 40px 20px;
        background-color: #fafafa;
        color: var(--text-color);
        line-height: 1.6;
      }

      .container {
        background: var(--bg-color);
        padding: 30px;
        border-radius: 16px;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
      }

      h1 {
        color: var(--primary-color);
        text-align: center;
        margin-bottom: 40px;
        font-weight: 700;
        font-size: 2.2em;
      }

      .upload-area {
        position: relative;
        margin: 20px 0;
        padding: 40px;
        border: 2px dashed var(--primary-light);
        border-radius: 12px;
        background: rgba(108, 92, 231, 0.03);
        text-align: center;
        transition: all 0.3s ease;
        cursor: pointer;
        overflow: hidden;
      }

      .upload-area:hover, .upload-area.dragover {
        border-color: var(--primary-color);
        background: rgba(108, 92, 231, 0.05);
      }

      .upload-area.dragover {
        transform: scale(1.02);
      }

      #fontFile {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        border: 0;
      }

      .upload-icon {
        font-size: 2em;
        color: var(--primary-color);
        margin-bottom: 15px;
      }

      .upload-text {
        color: var(--text-color);
        margin-bottom: 10px;
      }

      .upload-hint {
        color: var(--primary-light);
        font-size: 0.9em;
      }

      .file-name {
        margin-top: 10px;
        padding: 8px 16px;
        background: rgba(108, 92, 231, 0.1);
        border-radius: 6px;
        display: none;
      }

      #status {
        margin: 20px 0;
        padding: 15px;
        border-radius: 10px;
        background: rgba(108, 92, 231, 0.1);
        color: var(--primary-color);
        text-align: center;
        font-weight: 500;
        transition: all 0.3s ease;
      }

      #status.success {
        background: rgba(0, 184, 148, 0.1);
        color: var(--success-color);
      }

      #status.error {
        background: rgba(214, 48, 49, 0.1);
        color: var(--error-color);
      }

      textarea {
        width: 100%;
        height: 120px;
        padding: 15px;
        border: 2px solid var(--border-color);
        border-radius: 10px;
        resize: vertical;
        font-size: 16px;
        margin: 20px 0;
        box-sizing: border-box;
        transition: all 0.3s ease;
      }

      textarea:focus {
        outline: none;
        border-color: var(--primary-light);
        box-shadow: 0 0 0 3px rgba(108, 92, 231, 0.1);
      }

      .button-group {
        display: flex;
        gap: 12px;
        margin: 20px 0;
      }

      button {
        padding: 12px 28px;
        background: var(--primary-color);
        color: white;
        border: none;
        border-radius: 10px;
        cursor: pointer;
        font-size: 16px;
        font-weight: 600;
        transition: all 0.3s ease;
        flex: 1;
      }

      button:hover {
        background: var(--primary-light);
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(108, 92, 231, 0.2);
      }

      button:active {
        transform: translateY(0);
      }

      button:disabled {
        background: var(--border-color);
        cursor: not-allowed;
        transform: none;
        box-shadow: none;
        opacity: 0.7;
      }

      #downloadBtn {
        background: var(--success-color);
      }

      #downloadBtn:hover {
        background: #00d1a7;
        box-shadow: 0 4px 12px rgba(0, 184, 148, 0.2);
      }

      #downloadBtn:disabled {
        background: var(--border-color);
      }

      #preview {
        margin-top: 30px;
        padding: 30px;
        border: 2px solid var(--border-color);
        border-radius: 12px;
        min-height: 100px;
        font-size: 28px;
        text-align: center;
        background: var(--bg-color);
        transition: all 0.3s ease;
        word-wrap: break-word;
        word-break: break-all;
        overflow-wrap: break-word;
        white-space: pre-wrap;
        line-height: 1.5;
        overflow: auto;
        max-height: 300px;
      }

      #preview:empty {
        display: none;
      }

      @media (max-width: 600px) {
        body {
          padding: 20px 15px;
        }
        
        .container {
          padding: 20px;
        }

        .button-group {
          flex-direction: column;
          gap: 10px;
        }

        button {
          width: 100%;
          padding: 15px 28px;
        }

        h1 {
          font-size: 1.8em;
          margin-bottom: 30px;
        }

        .upload-area {
          padding: 20px;
        }

        #preview {
          padding: 20px;
          font-size: 24px;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h1>字体子集化工具</h1>

      <div class="upload-area" id="dropArea">
        <input type="file" id="fontFile" accept=".ttf,.otf,.woff,.woff2" />
        <div class="upload-icon">📁</div>
        <div class="upload-text">点击或拖拽上传字体文件</div>
        <div class="upload-hint">支持 TTF/OTF/woff/woff2 格式</div>
        <div class="file-name" id="fileName"></div>
      </div>

      <div id="status">请上传字体文件</div>

      <textarea id="textInput" placeholder="请输入需要保留的文字..."></textarea>

      <div style="margin-bottom: 15px;">
        <button id="addCommonChars" style="width: auto; padding: 8px 16px; font-size: 14px;">
          添加常见字符
        </button>
      </div>

      <div class="button-group">
        <button id="generateBtn">生成字体</button>
        <button id="downloadBtn" disabled>下载字体</button>
      </div>

      <div id="preview">预览区域</div>
    </div>

    <script>
      // 上传区域交互处理
      const dropArea = document.getElementById('dropArea');
      const fileInput = document.getElementById('fontFile');
      const fileName = document.getElementById('fileName');

      // 点击上传
      dropArea.addEventListener('click', () => {
        fileInput.click();
      });

      // 初始化状态
      const statusEl = document.getElementById('status');

      // 拖拽事件处理
      ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
        dropArea.addEventListener(eventName, preventDefaults, false);
      });

      function preventDefaults(e) {
        e.preventDefault();
        e.stopPropagation();
      }

      // 拖拽状态视觉反馈
      ['dragenter', 'dragover'].forEach(eventName => {
        dropArea.addEventListener(eventName, () => {
          dropArea.classList.add('dragover');
        });
      });

      ['dragleave', 'drop'].forEach(eventName => {
        dropArea.addEventListener(eventName, () => {
          dropArea.classList.remove('dragover');
        });
      });

      // 处理文件上传
      function handleFile(file) {
        // 检查文件类型
        if (!file.name.match(/\.(ttf|otf|woff|woff2)$/i)) {
          showStatus('请上传 TTF、OTF、WOFF 或 WOFF2 格式的字体文件', 'error');
          return false;
        }

        // 检查文件大小（最大 50MB）
        if (file.size > 50 * 1024 * 1024) {
          showStatus('文件大小不能超过 50MB', 'error');
          return false;
        }
        
        // 不直接修改fileInput.files，因为它在某些浏览器中是只读的
        // 我们只需要在生成字体时访问当前选择的文件
        updateFileName(file.name);
        showStatus('文件已选择：' + file.name, 'success');
        
        // 存储当前文件以供后续使用
        window.selectedFontFile = file;
        
        return true;
      }

      // 处理文件拖放
      dropArea.addEventListener('drop', (e) => {
        const dt = e.dataTransfer;
        const files = dt.files;
        
        if (files.length > 0) {
          handleFile(files[0]);
        }
      });

      // 文件选择变化
      fileInput.addEventListener('change', () => {
        if (fileInput.files.length > 0) {
          handleFile(fileInput.files[0]);
        }
      });

      // 更新文件名显示
      function updateFileName(name) {
        fileName.style.display = 'block';
        fileName.textContent = name;
      }

      // 显示状态信息
      function showStatus(message, type = '') {
        const statusEl = document.getElementById('status');
        statusEl.textContent = message;
        statusEl.className = ''; // 清除所有类
        statusEl.classList.add('status');
        if (type) {
          statusEl.classList.add(type);
        }
      }

      // 常见字符集合
      const commonChars = {
        chinese: "的一是在不了有和人这中大为上个国我以要他时来用们生到作地于出就分对成会可主发年动同工也能下过子说产种面而方后多定行学法所民得经十三之进着等部度家电力里如水化高自二理起小物现实加量都两体制机当使点从业本去把性好应开它合还因由其些然前外天政四日那社义事平形相全表间样与关各重新线内数正心反你明看原又么利比或但质气第向道命此变条只没结解问意建月公无系军很情者最立代想已通并提直题党程展五果料象员革位入常文总次品式活设及管特件长求老头基资边流路级少图山统接知较将组见计别她手角期根论运农指几九区强放决西被干做必战先回则任取据处队南给色光门即保治北造百规热领七海口东导器压志世金增争济阶油思术极交受联什认六共权收证改清己美再采转更单风切打白教速花带安场身车例真务具万每目至达走积示议声报斗完类八离华名确才科张信马节话米整空元况今集温传土许步群广石记需段研界拉林律叫且究观越织装影算低持音众书布复容儿须际商非验连断深难近矿千周委素技备半办青省列习响约支般史感劳便团往酸历市克何除消构府称太准精值号率族维划选标写存候毛亲快效斯院查江型眼王按格养易置派层片始却专状育厂京识适属圆包火住调满县局照参红细引听该铁价严龙飞",
        english: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
        numbers: "0123456789",
        punctuation: "，。、；：？！“”‘’（）【】《》…—～·"
      };

      // 添加常见字符功能
      document.getElementById("addCommonChars").addEventListener("click", () => {
        const textInput = document.getElementById("textInput");
        const currentText = textInput.value;
        
        // 添加常见字符，避免重复
        let newText = currentText;
        for (const type in commonChars) {
          for (const char of commonChars[type]) {
            if (!currentText.includes(char)) {
              newText += char;
            }
          }
        }
        
        textInput.value = newText;
        showStatus("已添加常见字符", "success");
      });

      // 生成字体功能
      document.getElementById("generateBtn").addEventListener("click", async () => {
        const text = document.getElementById("textInput").value;
        const previewEl = document.getElementById("preview");

        if (!window.selectedFontFile || !text) {
          showStatus("请先上传字体文件并输入文字", "error");
          return;
        }

        const downloadBtn = document.getElementById("downloadBtn");
        
        try {
          // 重置下载按钮状态
          downloadBtn.disabled = true;
          
          // 清理之前的URL对象
          if (window.currentFontUrl) {
            URL.revokeObjectURL(window.currentFontUrl);
            window.currentFontUrl = null;
          }
          
          showStatus("处理中...");

          // 读取字体文件
          const arrayBuffer = await new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = () => resolve(reader.result);
            reader.onerror = () => reject(new Error("字体文件读取失败"));
            reader.readAsArrayBuffer(window.selectedFontFile);
          });

          // 解析字体
          const font = await opentype.parse(arrayBuffer);

          // 收集需要的字形
          const glyphs = [font.glyphs.get(0)]; // 包含.notdef
          const chars = new Set(text);
          for (const char of chars) {
            const glyph = font.charToGlyph(char);
            if (glyph) glyphs.push(glyph);
          }

          // 创建子集字体
          const subsetFont = new opentype.Font({
            familyName: "Subset Font",
            styleName: "Regular",
            unitsPerEm: font.unitsPerEm,
            ascender: font.ascender,
            descender: font.descender,
            glyphs: glyphs,
          });

          // 生成字体文件
          const fontArray = subsetFont.toArrayBuffer();
          const blob = new Blob([fontArray], { type: "font/ttf" });
          const url = URL.createObjectURL(blob);

          // 预览
          const fontFace = new FontFace("SubsetFont", `url(${url})`);
          await fontFace.load();
          document.fonts.add(fontFace);
          previewEl.textContent = text;
          previewEl.style.fontFamily = "SubsetFont, sans-serif";

          showStatus("字体生成成功！", "success");
          
          // 存储当前的URL，以便后续清理
          window.currentFontUrl = url;
          
          // 启用并设置下载按钮
          downloadBtn.disabled = false;
          downloadBtn.onclick = () => {
            const a = document.createElement("a");
            a.href = window.currentFontUrl;
            a.download = "subset-font.ttf";
            a.click();
            
            // 下载后清理URL
            URL.revokeObjectURL(window.currentFontUrl);
            window.currentFontUrl = null;
            
            // 重置下载按钮状态
            downloadBtn.disabled = true;
            downloadBtn.onclick = null;
          };
        } catch (error) {
          statusEl.textContent = "错误: " + error.message;
          console.error(error);
        }
      });
    </script>
  </body>
</html>